package ru.alt22.visor.php.ui.views;

//import org.eclipse.core.resources.IProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.TreeSelection;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TreeItem;

import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;

import ru.alt22.visor.php.ui.PDToolsUIPlugin;
import ru.alt22.visor.php.ui.swt.PHPTestsViewer;
import ru.alt22.visor.php.ui.swt.TestResultDetails;
import ru.alt22.visor.php.unittests.core.PHPTest;
import ru.alt22.visor.php.unittests.core.PHPTestCase;
import ru.alt22.visor.php.unittests.core.PHPTestListenter;
import ru.alt22.visor.php.unittests.core.PHPTestSuite;
import ru.alt22.visor.php.unittests.run.PHPTestRunner;

public class UnitTestsView extends ViewPart implements PHPTestListenter {
	private PHPTestsViewer viewer;
	private Action collapseAll;
	private Action expandAll;
	private Action reloadSelectedTests;
	private Action reloadProjectTests;
	private Action reloadAllTests;
	private Action runSelectedTests;
	private Action runAllTests;
	private Action runCheckedTests;
	private Action runFailedTests;
	private Action checkAllTests;
	private Action checkInvert;
	private TestResultDetails details;

	public void createPartControl(Composite parent) {
		createActions();
		createView(parent);
		createToolbar();
		PHPTestRunner.instance().addListener(this);
	}

	private void createActions() {
		collapseAll = new Action() {
			public void run() {
				viewer.collapseAll();
			}
		};
		collapseAll.setText("Collapse all tests");
		collapseAll.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/collapse-all.gif"));
		
		expandAll = new Action() {
			public void run() {
				viewer.expandAll();
			}
		};
		expandAll.setText("Expand all tests");
		expandAll.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/expand-all.gif"));

		reloadAllTests = new Action() {
			public void run() {
				setInputData();
			}
		};
		reloadAllTests.setText("Reload all tests");
		reloadAllTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/reload-all.gif"));

		reloadProjectTests = new Action() {
			public void run() {
/*
				TreeSelection selection = (TreeSelection)viewer.getSelection();
				if (selection.isEmpty()) {
					return;
				}
				TreeItem element = (TreeItem) selection.getFirstElement(); 
				while (!(element.getData() instanceof IProject) && (element != null)) {
					element = element.getParentItem();
				}
				if (null == element) {
					return;
				}
				viewer.refresh(element, true);
*/
			}
		};
		reloadProjectTests.setText("Reload selected project tests");
		reloadProjectTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/reload-project.gif"));

		reloadSelectedTests = new Action() {
			public void run() {
/*
				TreeSelection selection = (TreeSelection)viewer.getSelection();
				if (selection.isEmpty()) {
					return;
				}
				viewer.refresh(selection.getFirstElement(), true);
*/
			}
		};
		reloadSelectedTests.setText("Reload selected test");
		reloadSelectedTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/reload-selected.gif"));

		runSelectedTests = new Action() {
			public void run() {
				runSelectedTest();
			}
		};
		runSelectedTests.setText("Run selected tests");
		runSelectedTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/run-selected.gif"));
		
		runAllTests = new Action() {
			public void run() {
				PHPTestSuite suite = new PHPTestSuite("All Tests");
				TreeItem[] items = viewer.getTree().getItems();
				addToSuite(suite, items);
				PHPTestRunner.instance().run(suite);
			}
			
			private void addToSuite(PHPTestSuite suite, TreeItem[] items) {
				for (int i = 0; i < items.length; i++) {
					if (items[i].getData() instanceof PHPTestSuite) {
						PHPTestSuite test = (PHPTestSuite)items[i].getData(); 
						suite.addTest(test);
						continue;
					}
					
					if (items[i].getItemCount() > 0) {
						addToSuite(suite, items[i].getItems());
						continue;
					}
				}
			}
		};
		runAllTests.setText("Run all tests");
		runAllTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/run-all.gif"));

		runCheckedTests = new Action() {
			public void run() {
				PHPTestSuite suite = new PHPTestSuite("Checked Tests");
				TreeItem[] items = viewer.getTree().getItems();
				addToSuite(suite, items);
				PHPTestRunner.instance().run(suite);
			}
			
			private void addToSuite(PHPTestSuite suite, TreeItem[] items) {
				for (int i = 0; i < items.length; i++) {
					if (!items[i].getChecked()) {
						continue;
					}
					if (items[i].getItemCount() > 0) {
						addToSuite(suite, items[i].getItems());
						continue;
					}
					if (!(items[i].getData() instanceof PHPTestCase)) {
						continue;
					}
					
					PHPTestCase test = (PHPTestCase)items[i].getData(); 
					suite.addTest(test);
				}
			}
		};
		runCheckedTests.setText("Run checked tests");
		runCheckedTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/run-checked.gif"));
		
		runFailedTests = new Action() {
			public void run() {
			}
		};
		runFailedTests.setText("Run checked tests");
		runFailedTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/run-failed.gif"));

		checkAllTests = new Action() {
			public void run() {
				viewer.setAllChecked(true);
			}
		};
		checkAllTests.setText("Check all tests");
		checkAllTests.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/check-all.gif"));
		
		checkInvert = new Action() {
			public void run() {
				setChecked(viewer.getTree().getItems());
			}

			private void setChecked(TreeItem[] items) {
				for (int i = 0; i < items.length; i++) {
					TreeItem item = items[i];
					setChecked(item.getItems());
					if (item.getGrayed()) {
						continue;
					}
					item.setChecked(!item.getChecked());
				}
			}
		};
		checkInvert.setText("Check invert");
		checkInvert.setImageDescriptor(PDToolsUIPlugin.getImageDescriptor("icons/actions/check-invert.gif"));
	}

	private void createToolbar() {
		IActionBars bars = getViewSite().getActionBars();
		fillToolBar(bars.getToolBarManager());
	}

	private void fillToolBar(IToolBarManager toolbar) {
		toolbar.add(collapseAll);
		toolbar.add(expandAll);
		toolbar.add(new Separator());
		toolbar.add(checkAllTests);
		toolbar.add(checkInvert);
		toolbar.add(new Separator());
		toolbar.add(reloadAllTests);
		toolbar.add(reloadProjectTests);
		toolbar.add(reloadSelectedTests);
		toolbar.add(new Separator());
		toolbar.add(runFailedTests);
		toolbar.add(runSelectedTests);
		toolbar.add(runCheckedTests);
		toolbar.add(runAllTests);
	}

	private void createView(Composite parent) {
		parent.setLayout(new FillLayout(SWT.VERTICAL));

		viewer = new PHPTestsViewer(parent, this);
		details = null;
	}

	private TestResultDetails createDetails(Composite parent) {
		TestResultDetails details = new TestResultDetails(parent, this);
		parent.layout();

		return details;
	}

	public void runSelectedTest() {
		TreeSelection selection = (TreeSelection)viewer.getSelection();
		if (selection.isEmpty() || !(selection.getFirstElement() instanceof PHPTest)) {
			return;
		}
		PHPTestRunner.instance().run((PHPTest)selection.getFirstElement());
	}

	public void showTestDetails() {
		TreeSelection selection = (TreeSelection)viewer.getSelection();
		if (selection.isEmpty()) {
			return;
		}
		if (!(selection.getFirstElement() instanceof PHPTestCase)) {
			return;
		}

		PHPTestCase test = (PHPTestCase) selection.getFirstElement();
		if (null == test.getResult()) {
			return;
		}

		if (null == details) {
			details = createDetails(viewer.getTree().getParent());
		}

		details.setDetails(test.getResult().getErrorMessage());
	}

	public void hideTestDetails() {
		if (null == details) {
			return;
		}
		details.dispose();
		details = null;
		viewer.getTree().getParent().layout();
	}

	private void setInputData() {
		viewer.setInput("root");
	}

	public void setFocus() {
		viewer.getTree().setFocus();
	}

	public void testSuiteStarted(PHPTestSuite suite) {
	}

	public void testSuiteFinished(PHPTestSuite suite) {
		viewer.refresh(suite);
	}

	public void testCaseStarted(PHPTestCase test) {
	}

	public void testCaseFinished(PHPTestCase test) {
		viewer.refresh(test);
	}

    public void dispose() {
    	viewer.getTree().dispose();
    	if (null != details) {
    		details.dispose();
    	}
		PHPTestRunner.instance().removeListener(this);
    	super.dispose();
    }
}